package com.zjjc.QZEnergy.utils;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.zjjc.QZEnergy.vo.ReportData;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.http.*;
import org.springframework.web.client.RestTemplate;


import java.security.*;

import java.util.*;



public class HttpsPostUtil {

    private static String privateKey = "297fb5b1c5b573bc74389c348afed396695291a201bb3135e5c54ee05a4823d4";

    /**
     * 数据请求
     * @param appId
     * @param dataList 认证时list为null，上传时list应为各站点的区间数据
     * @return
     */
    public static ResponseEntity<String> sendDataPostRequest(String appId, List<ReportData> dataList, String url, String SM4Str) throws Exception {
        // 生成时间戳和随机字符串
        long timestamp = System.currentTimeMillis() / 1000;
        String nonce = UUID.randomUUID().toString().replace("-", "");
        System.out.println("nonce = " + nonce);

        // 构建请求体（未加密）
        Map<String, String> requestBodyMap = new HashMap<>();
        if (dataList != null){
            requestBodyMap.put("data", encryptData(dataList,SM4Str));
        }

        String requestBodyJson = convertToJson(requestBodyMap);

        // 生成签名
        String signature = generateDataSignature(appId, timestamp, nonce,convertToJson(dataList));
        System.out.println("signature = " + signature);

        // 构建请求头
        HttpHeaders headers = new HttpHeaders();
//        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("Content-Type", "application/json;charset=UTF-8");
        headers.set("X-App-Id", appId);
        headers.set("X-Timestamp", String.valueOf(timestamp));
        headers.set("X-Nonce", nonce);
        headers.set("X-Signature", signature);

        // 创建请求实体
        HttpEntity<String> requestEntity = new HttpEntity<>(requestBodyJson, headers);
        System.out.println("数据接口请求示例 = " + requestEntity.toString());

        // 发送 POST 请求
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
    }

    /**
     * 认证请求
     * @param appId
     * @param url
     * @return
     * @throws Exception
     */
    public static ResponseEntity<String> sendAuthPostRequest(String appId, String url) throws Exception {
        // 生成时间戳和随机字符串
        long timestamp = System.currentTimeMillis() / 1000;
        String nonce = UUID.randomUUID().toString().replace("-", "");
        System.out.println("nonce = " + nonce);

        String requestBodyJson = convertToJson(null);

        // 生成签名
        String signature = generateAuthSignature(appId, timestamp, nonce);
        System.out.println("signature = " + signature);

        // 构建请求头
        HttpHeaders headers = new HttpHeaders();
//        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("Content-Type", "application/json;charset=UTF-8");
        headers.set("X-App-Id", appId);
        headers.set("X-Timestamp", String.valueOf(timestamp));
        headers.set("X-Nonce", nonce);
        headers.set("X-Signature", signature);

        // 创建请求实体
        HttpEntity<String> requestEntity = new HttpEntity<>(requestBodyJson, headers);
        System.out.println("requestEntity.getHeaders() = " + requestEntity.getHeaders());
        System.out.println("requestEntity.getBody() = " + requestEntity.getBody());

        // 发送 POST 请求
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
    }

    /**
     *
     * @param data  解密数据 SM2
     * @param privateKey  SM2秘钥
     * @return
     */
    private String decryptData(String data,String privateKey) {
        String result = CryptoUtils.sm2Decrypt(privateKey,data);
        return result;
    }

    /**
     * SM4加密
     * @param dataList
     * @param string
     * @return
     */
    private static String encryptData(List<ReportData> dataList, String string) {
        String data = convertToJson(dataList);
        String SM4pri = string.substring(0, 32); //sm4秘钥
        String IV = string.substring(32); //IV向量
        //在这个地方写 加密逻辑
        String result = CryptoUtils.sm4Encrypt(SM4pri, data, IV);

        return result;
    }

    /**
     * DEEPSEEK版本  签名过程
     * @param appId
     * @param timestamp
     * @param nonce
     * @param data
     * @return
     * @throws Exception
     */
//    public static String generateSignature(String appId, long timestamp, String nonce, String data) throws Exception{
//        //在这个地方写 签名逻辑
//
//        Security.addProvider(new BouncyCastleProvider());
//
//        String s;
//        if (data != null){
//            s = "appId="+appId+"&data={"+ data + "}&nonce="+ nonce + "&timestamp="+ timestamp;
//        }else {
//            s = "appId="+appId+"&data={}&nonce="+ nonce + "&timestamp="+ timestamp;
//        }
//        String sha256 = getSHA256(s);
//
//        byte[] message = sha256.getBytes();
//        byte[] sign = sign(message, Hex.decode(privateKey));
//        System.out.println("签名结果 = " + sign);
//        return sign.toString();
//    }

    /**
     * 官方版本  上传签名过程
     * @param appId
     * @param timestamp
     * @param nonce
     * @param data
     * @return
     * @throws Exception
     */
    public static String generateDataSignature(String appId, long timestamp, String nonce, String data) throws Exception{
        //在这个地方写 签名逻辑

        Security.addProvider(new BouncyCastleProvider());

        String s = "appId="+appId+"&data="+ data + "&nonce="+ nonce + "&timestamp="+ timestamp;

        String sha256 = getSHA256(s);
        System.out.println("s = " + s);

        return CryptoUtils.sm2Sign(privateKey,sha256);
    }

    /**
     * 认证签名过程
     * @param appId
     * @param timestamp
     * @param nonce
     * @return
     * @throws Exception
     */
    public static String generateAuthSignature(String appId, long timestamp, String nonce) throws Exception{
        //在这个地方写 签名逻辑

        Security.addProvider(new BouncyCastleProvider());

        String s = "appId="+appId+"&data={}&nonce="+ nonce + "&timestamp="+ timestamp;

        String sha256 = getSHA256(s);
        System.out.println("s = " + s);

        return CryptoUtils.sm2Sign(privateKey,sha256);
    }

    /**
     * 字符串SHA256哈希工具方法
     * @param input
     * @return
     */
    public static String getSHA256(String input) {
        try {
            // 获取SHA-256 MessageDigest 实例
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            // 对字符串进行编码处理
            byte[] hashBytes = digest.digest(input.getBytes());
            // 将字节数组转换为十六进制字符串
            StringBuilder hexString = new StringBuilder();
            for (byte b : hashBytes) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) hexString.append('0');
                hexString.append(hex);
            }
            return hexString.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("SHA-256 algorithm not found.");
        }
    }

    /**
     * 转JSON工具方法
     * @param obj
     * @return
     */
    public static String convertToJson(Object obj) {
        if (obj == null){
            String s = new ObjectMapper().createObjectNode().toString();
            return s;
        }
        try {
            com.fasterxml.jackson.databind.ObjectMapper objectMapper = new com.fasterxml.jackson.databind.ObjectMapper();
            return objectMapper.writeValueAsString(obj);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

}
